﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace OneDollarStore.Models
{
    public partial class ShoppingCartModel
    {
        StoreModelEntities storeDB = new StoreModelEntities();

        private string shoppingCartId { get; set; }

        public const string CartSessionKey = "CartId";

        private string GetCartId(HttpContextBase context)
        {
            if (context.Session[CartSessionKey] == null)
            {
                if (!string.IsNullOrEmpty(context.User.Identity.Name))
                {
                    // User is logged in
                    context.Session[CartSessionKey] = context.User.Identity.Name;
                }
                else
                {
                    // Anonymous user, assign a temporary key value
                    Guid tempCartId = Guid.NewGuid();
                    context.Session[CartSessionKey] = tempCartId.ToString();
                }
            }
            return context.Session[CartSessionKey].ToString();
        }

        public static ShoppingCartModel GetCart(HttpContextBase context)
        {
            var cart = new ShoppingCartModel();
            cart.shoppingCartId = cart.GetCartId(context);
            return cart;
        }

        // Add a record to Cart table or update its product's quantity
        public void AddToCart(SerialProduct product)
        {
            var cartItem = storeDB.Carts.FirstOrDefault(c => c.CartID == shoppingCartId && 
                c.SerialProduct.SerialProductID == product.SerialProductID);
            if (cartItem == null)
            {
                var _product = storeDB.SerialProducts.FirstOrDefault(d => d.SerialProductID == product.SerialProductID);
                cartItem = new Cart
                {
                    CartID = shoppingCartId,
                    Count = 1,
                    DateCreated = DateTime.Now,
                    SerialProduct = _product
                };
                storeDB.AddToCarts(cartItem);
            }
            else
            {
                // This product already exists in cart, so increase its quantity
                cartItem.Count++;
            }
            storeDB.SaveChanges();
        }

        // Remove a record from Cart table or update it's product's quantity
        // id: RecordID
        public void RemoveFromCart(int id)
        {
            var cartItem = storeDB.Carts.FirstOrDefault(c => c.CartID == shoppingCartId && c.RecordID == id);
            if (cartItem != null)
            {
                if (cartItem.Count > 1)
                {
                    cartItem.Count--;
                }
                else
                {
                    storeDB.DeleteObject(cartItem);
                }
                storeDB.SaveChanges();
            }
        }

        // Delete all products from this cart
        private void EmptyCart()
        {
            var cartItems = storeDB.Carts.Where(c => c.CartID == shoppingCartId);
            foreach (var cartItem in cartItems)
            {
                storeDB.DeleteObject(cartItem);
            }
            storeDB.SaveChanges();
        }

        // Get all products from this cart
        public List<Cart> GetCartItems()
        {
            var cartItems = (from cart in storeDB.Carts.Include("SerialProduct")
                             where cart.CartID == shoppingCartId
                             select cart);
            return cartItems.ToList();
        }

        // Sum all products' quantity in this cart
        public int GetCount()
        {
            int? count = (from cart in storeDB.Carts
                          where cart.CartID == shoppingCartId
                          select (int?)cart.Count).Sum();
            return count ?? 0;
        }

        // Sum all products' total in this cart
        public decimal GetTotal()
        {
            var items = (from cart in storeDB.Carts
                         where cart.CartID == shoppingCartId
                         select new { cart.SerialProduct, cart.Count, cart.SerialProduct.RetailPrice, cart.SerialProduct.PromotionPrice, cart.SerialProduct.PromotionEndDate });
            decimal? total = 0;
            foreach (var item in items)
            {
                if (!String.IsNullOrEmpty(item.PromotionPrice.ToString()) && (DateTime.Now.Date <= item.PromotionEndDate))
                {
                    total += item.Count * item.PromotionPrice;
                }
                else
                {
                    total += item.Count * item.RetailPrice;
                }
            }
            return total ?? 0;
        }

        // Create order details for this cart based on order
        public void CreateOrderDetails(Order order)
        {
            var _order = storeDB.Orders.FirstOrDefault(o => o.OrderID == order.OrderID);
            decimal orderTotal = 0;
            var cartItems = GetCartItems();
            foreach (var cartItem in cartItems)
            {
                if (!String.IsNullOrEmpty(cartItem.SerialProduct.PromotionPrice.ToString()) && (DateTime.Now.Date <= cartItem.SerialProduct.PromotionEndDate))
                {
                    var orderDetails = new OrderDetail
                    {
                        SerialProduct = cartItem.SerialProduct,
                        Order = _order,
                        UnitPrice = (cartItem.SerialProduct.PromotionPrice ?? 0),
                        Quantity = cartItem.Count
                    };
                    storeDB.AddToOrderDetails(orderDetails);
                    orderTotal += (cartItem.Count * (cartItem.SerialProduct.PromotionPrice ?? 0));
                }
                else
                {
                    var orderDetails = new OrderDetail
                    {
                        SerialProduct = cartItem.SerialProduct,
                        Order = _order,
                        UnitPrice = cartItem.SerialProduct.RetailPrice,
                        Quantity = cartItem.Count
                    };
                    storeDB.AddToOrderDetails(orderDetails);
                    orderTotal += (cartItem.Count * cartItem.SerialProduct.RetailPrice);
                }
                cartItem.SerialProduct.Quantity -= cartItem.Count;
                if (cartItem.SerialProduct.Quantity <= 0)
                {
                    cartItem.SerialProduct.Highlight = false;
                }
            }
            _order.Total = orderTotal;
            // Save order
            storeDB.SaveChanges();
            // Empty the shopping cart
            EmptyCart();
        }

        // Migration
        public void MigrateCart(string username)
        {
            var shoppingCart = storeDB.Carts.Where(c => c.CartID == shoppingCartId);
            foreach (Cart Item in shoppingCart)
            {
                Item.CartID = username;
            }
            storeDB.SaveChanges();
        }
    }

    public class ShoppingCartViewModel
    {
        public List<Cart> CartItems { get; set; }
        public decimal CartTotal { get; set; }
    }

    public class ShoppingCartRemoveViewModel
    {
        public string Message { get; set; }
        public decimal CartTotal { get; set; }
        public int CartCount { get; set; }
        public int DeletedID { get; set; }
    }
}